package com.csdig.cms.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.csdig.cms.dao.ChannelAttrDAO;
import com.csdig.cms.dao.ChannelDAO;
import com.csdig.cms.dao.ModelItemDAO;
import com.csdig.cms.dao.cache.ChannelCacheDAO;
import com.csdig.cms.exception.BusinessException;
import com.csdig.cms.model.Channel;
import com.csdig.cms.model.ChannelAttr;
import com.csdig.cms.model.ModelItem;
import com.csdig.cms.service.ChannelService;
import com.csdig.db.DBUtils;

@Service
@Transactional
public class ChannelServiceImpl implements ChannelService {

	@Autowired
	private ChannelDAO channelDao;

	@Autowired
	private ChannelAttrDAO channelAttrDao;

	@Autowired
	private ModelItemDAO modelItemDao;

	@Autowired
	private ChannelCacheDAO channelCacheDao;
	
	@Override
	public Channel getById(int id) throws Exception {
		return channelDao.findById(id);
	}

	@Override
	public List<Channel> listAll(Integer pid) throws Exception {
		return channelDao.findByPId(pid);
	}

	@Override
	public void add(Channel channel) throws Exception {
		List<Channel> list = channelDao.findByCondition(new String[] { "channel_path", "parent_id" }, new Object[] {
				channel.getChannelPath(), channel.getParentId() });
		if (list != null && list.size() > 0) {
			throw new BusinessException("", "栏目路径已存在");
		}
		channelDao.add(channel);
		Long channelId = DBUtils.getLastInsertID();
		addChannelAttr(channelId.intValue(), channel.getTplPath());
	}

	//
	public void addChannelAttr(Integer channelId, String tplPath) throws Exception {
		List<ModelItem> modelItemList = modelItemDao.findbyPath(tplPath);
		if (modelItemList != null && modelItemList.size() > 0) {
			for (ModelItem modelItem : modelItemList) {
				ChannelAttr attr = new ChannelAttr();
				attr.setChannelId(channelId);
				attr.setAttrName(modelItem.getField());
				if (StringUtils.isNotEmpty(modelItem.getDefValue())) {
					attr.setAttrValue(modelItem.getDefValue());
				}
				attr.setPriority(Integer.valueOf(1));
				channelAttrDao.add(attr);
			}

		}
	}

	@Override
	public void update(Channel channel) throws Exception {
		Channel oldRecord = channelDao.findById(channel.getChannelId());
		// 如果模板改变了，清空栏目属性数据
		if (!StringUtils.equals(oldRecord.getTplPath(), channel.getTplPath())) {
			channelAttrDao.deleteByChannelId(channel.getChannelId());
		}
		channelDao.update(channel);
		addChannelAttr(channel.getChannelId(), channel.getTplPath());
	}

	@Override
	public void delete(int id) throws Exception {
		List<Channel> list = channelDao.findByPId(id);
		if (list != null && list.size() > 0) {
			throw new BusinessException("", "栏目存在子栏目，不能删除");
		}
		channelAttrDao.deleteByChannelId(id);
		channelDao.delete(id);
	}

	@Override
	public void cleanDirtyData() throws Exception {

	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Map<String, Object>> listChanelTreeByPid(Integer id) throws Exception {
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		if (id == null) {
			Map<String, Object> root = new HashMap<String, Object>();
			root.put("id", "-1");
			root.put("text", "根节点");
			root.put("iconCls", "icon_folder");
			root.put("state", "closed");
			result.add(root);
			return result;
		}

		List<Channel> list = channelDao.findByPId(id);
		if (list != null) {
			for (Channel channel : list) {
				Map<String, Object> map = new HashMap<String, Object>();
				map = BeanUtils.describe(channel);
				map.put("id", channel.getChannelId());
				map.put("text", channel.getChannelName());
				List<Channel> child = channelDao.findByPId(channel.getChannelId());
				if (channel != null && child.size() > 0) {
					map.put("iconCls", "icon_folder");
					map.put("state", "closed");
				} else {
					map.put("iconCls", "icon-edit-file");
					map.put("state", "open");
				}
				result.add(map);
			}
		}

		return result;
	}

	@Override
	public List<Integer> getNestChannelIdsByPid(Integer pid, boolean includeSelf) throws Exception {
		List<Integer> result = new ArrayList<Integer>();
		List<Channel> list = channelDao.findByPId(pid);
		while (list != null && list.size() > 0) {
			Integer[] tempPids = new Integer[list.size()];
			for (int i = 0; i < list.size(); i++) {
				Channel c = list.get(i);
				result.add(c.getChannelId());
				tempPids[i] = c.getChannelId();
			}
			list = channelDao.findByPIds(tempPids);
		}
		if (includeSelf) {
			Channel channel = channelDao.findById(pid);
			if (channel != null) {
				result.add(channel.getChannelId());
			}
		}

		return result;
	}

	@Override
	public List<Integer> getNestContentChannelIdsByPid(Integer pid, boolean includeSelf) throws Exception {
		List<Integer> result = new ArrayList<Integer>();
		List<Channel> list = channelDao.findByCondition(new String[] { "parent_id", "is_single" }, new Object[] { pid,
				Boolean.FALSE });
		while (list != null && list.size() > 0) {
			Integer[] tempPids = new Integer[list.size()];
			for (int i = 0; i < list.size(); i++) {
				Channel c = list.get(i);
				if (!c.getIsSingle()) {
					result.add(c.getChannelId());
				}
				tempPids[i] = c.getChannelId();
			}
			list = channelDao.findByPIds(tempPids);
		}
		if (includeSelf) {
			Channel channel = channelDao.findById(pid);
			if (channel != null && !channel.getIsSingle()) {
				result.add(channel.getChannelId());
			}
		}

		return result;
	}

	@Override
	public Channel findByPath(String path) throws Exception {
		List<Channel> list = channelDao.findByCondition(new String[] { "channel_path" }, new Object[] { path });
		if (list != null && list.size() > 0) {
			Channel channel = list.get(0);
			List<ChannelAttr> attrList = channelAttrDao.findByChannelId(channel.getChannelId());
			if (attrList != null) {
				channel.setAttrs(attrList);
			}
			return list.get(0);
		}
		return null;
	}

	@Override
	@Transactional(readOnly = true)
	public List<Channel> getChildListForTag(Integer parentId, Boolean isDisplay, Boolean showChild) {
		try {
			List<Channel> list = channelCacheDao.findByCondiFromCache(parentId, isDisplay, " order by priority");
//			List<Channel> list = channelDao.findByCondition(new String[] { "parent_id", "is_display" }, new Object[] {
//					parentId, isDisplay }, " order by priority");
			if (showChild && list != null && list.size() > 0) {
				for (Channel channel : list) {
					channel.setChildren(getChildListForTag(channel.getChannelId(), isDisplay, showChild));
				}
			}
			return list;
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage());
		}
	}

}
